package fr.blogger.ejb.facade;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

public abstract class AbstractFacade<T> {

	@PersistenceContext
	protected EntityManager em;
	protected Class entityClass;

	public AbstractFacade() {
	}

	@PostConstruct
	private void initialisation() {
		entityClass = (Class) ((java.lang.reflect.ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public T find(final Serializable id) {
		return (T) em.find(entityClass, id);
	}

	public List<T> findAll() {
		CriteriaQuery query = initQuery();
		return em.createQuery(query).getResultList();
	}

	public T create(final T entity) {
		try {
			em.persist(entity);
			return entity;
		} catch (ConstraintViolationException e) {
			generateValidationException(e);
			return null;
		}
	}

	public T update(final T entity) {
		try {
			em.merge(entity);
			return entity;
		} catch (ConstraintViolationException e) {
			generateValidationException(e);
			return null;
		}
	}

	public void delete(final T entity) {
		em.remove(entity);
	}

	protected CriteriaBuilder builder() {
		return em.getCriteriaBuilder();
	}

	protected CriteriaQuery initQuery() {
		return builder().createQuery(entityClass);
	}

	private void generateValidationException(ConstraintViolationException exception) {
		for (ConstraintViolation constraint : exception.getConstraintViolations()) {
			System.out.println(String.format("%s => %s", constraint.getPropertyPath(), constraint.getMessage()));
		}
	}

}
